You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { Button, Grid, Tab, Tabs, Typography } from '@mui/material';
  2. import { Box, Container } from '@mui/system';
  3. import { dehydrate, QueryClient } from '@tanstack/react-query';
  4. import Image from 'next/image';
  5. import { useRouter } from 'next/router';
  6. import React, { useState } from 'react';
  7. import Loader from '../../components/loader/Loader';
  8. import ProductCard from '../../components/product-card/ProductCard';
  9. import TabPanel from '../../components/tab-panel/TabPanel';
  10. import {
  11. useFetchSimilarProducts,
  12. useFetchSingleProduct,
  13. } from '../../hooks/useFetchProductData';
  14. import { getProductData } from '../../requests/products/producDataRequest';
  15. import { useStore, useStoreUpdate } from '../../store/cart-context';
  16. import { shuffle } from '../../utils/helpers/shuffle';
  17. const SingleProduct = () => {
  18. const { addCartValue } = useStoreUpdate();
  19. const { cartStorage } = useStore();
  20. const router = useRouter();
  21. const { customId } = router.query;
  22. const { data, isLoading } = useFetchSingleProduct(customId);
  23. const productCategory = data?.product.category;
  24. const { data: similarProducts, isLoading: similarLoading } =
  25. useFetchSimilarProducts(productCategory);
  26. const [value, setValue] = useState(0);
  27. const addProductToCart = (quantity) => addCartValue(data.product, quantity);
  28. const inCart = cartStorage?.some(
  29. (item) => item.product.customID === data?.product.customID
  30. )
  31. ? true
  32. : false;
  33. const handleChange = (event, newValue) => {
  34. setValue(newValue);
  35. };
  36. function a11yProps(index) {
  37. return {
  38. id: `simple-tab-${index}`,
  39. 'aria-controls': `simple-tabpanel-${index}`,
  40. };
  41. }
  42. if (isLoading) {
  43. return <Loader loading={isLoading} />;
  44. }
  45. if (similarLoading) {
  46. return <Loader loading={similarLoading} />;
  47. }
  48. const productsToShow = (id) => {
  49. const filtered = shuffle(similarProducts?.productsByCategory)
  50. .filter((product) => product.customID !== id)
  51. .slice(0, 3)
  52. .map((item) => (
  53. <Grid
  54. key={item._id}
  55. item
  56. lg={4}
  57. md={6}
  58. sm={6}
  59. xs={12}
  60. sx={{ mb: '100px' }}
  61. >
  62. <ProductCard product={item} />
  63. </Grid>
  64. ));
  65. return filtered;
  66. };
  67. return (
  68. <Box
  69. sx={{
  70. display: 'flex',
  71. flexDirection: 'column',
  72. }}
  73. >
  74. <Container>
  75. <Typography
  76. fontFamily={'body1.fontFamily'}
  77. fontSize="32px"
  78. sx={{ mt: 25, height: '100%', color: 'primary.main' }}
  79. >
  80. {data.product.name}
  81. </Typography>
  82. <Grid container spacing={2}>
  83. <Grid item md={6} sm={12}>
  84. <Image
  85. src="/images/product-card-image.jpg"
  86. alt="product"
  87. width={900}
  88. height={600}
  89. />
  90. </Grid>
  91. <Grid item xs={12} md={6}>
  92. <Tabs
  93. sx={{
  94. '& button:focus': {
  95. borderTop: '1px solid black',
  96. borderLeft: '1px solid black',
  97. borderRight: '1px solid black',
  98. borderRadius: '5px 5px 0 0',
  99. borderBottom: 'none',
  100. },
  101. }}
  102. value={value}
  103. onChange={handleChange}
  104. aria-label="basic tabs example"
  105. >
  106. <Tab
  107. sx={{
  108. width: '50%',
  109. }}
  110. label="Purchase"
  111. {...a11yProps(0)}
  112. />
  113. <Tab sx={{ width: '50%' }} label="Category" {...a11yProps(1)} />
  114. </Tabs>
  115. <TabPanel value={value} index={0}>
  116. <Box flexGrow={2} sx={{ pb: { xs: '70px' } }}>
  117. <Typography>{data.product.description}</Typography>
  118. </Box>
  119. <Box
  120. sx={{
  121. display: { xs: 'flex' },
  122. flexDirection: { xs: 'column' },
  123. justifyContent: { xs: 'center' },
  124. alignItems: { xs: 'center', md: 'flex-end' },
  125. }}
  126. >
  127. <Typography mb={2}>${data.product.price}</Typography>
  128. <Button
  129. disabled={inCart}
  130. onClick={() => addProductToCart(1)}
  131. sx={{
  132. backgroundColor: '#CBA213',
  133. height: 50,
  134. width: { xs: '300px', md: '150px' },
  135. color: 'white',
  136. }}
  137. >
  138. {inCart ? 'In Cart' : 'Add to cart'}
  139. </Button>
  140. </Box>
  141. </TabPanel>
  142. <TabPanel value={value} index={1}>
  143. <Box sx={{ mb: { xs: '60px' } }}>{data.product.category}</Box>
  144. </TabPanel>
  145. </Grid>
  146. </Grid>
  147. <Typography
  148. sx={{
  149. mt: { xs: '60px', md: '100px', lg: '150px' },
  150. mb: 5,
  151. color: 'primary.main',
  152. fontSize: '32px',
  153. }}
  154. >
  155. Other Product You May Like
  156. </Typography>
  157. <Grid container spacing={2}>
  158. {productsToShow(customId)}
  159. </Grid>
  160. </Container>
  161. </Box>
  162. );
  163. };
  164. export const getServerSideProps = async (context) => {
  165. const { params } = context;
  166. const { customId } = params;
  167. const queryClient = new QueryClient();
  168. await queryClient.prefetchQuery(
  169. ['product', customId],
  170. async () => await getProductData(customId)
  171. );
  172. return {
  173. props: {
  174. dehydratatedState: dehydrate(queryClient),
  175. },
  176. };
  177. };
  178. export default SingleProduct;